package connect4.swing2;

import java.util.ArrayList;
import java.util.Random;

import javax.jws.WebParam.Mode;

import connect4.Connect4Model;
import connect4.Piece;

public class YiuAI {
	private final Connect4Model model;
	private int boardsAnalysed;
	private int colToPlay;
	private Piece opponent;
	private Piece player;

	public YiuAI(Connect4Model model) {
		this.model = model;
		this.boardsAnalysed = 0;
		this.colToPlay = -1;
				
	}

	public int getBoardsAnalysed() {
		return boardsAnalysed;
	}

	public int colToPlay(Piece player) {
		this.player = player;
		if(player == Piece.BLACK){
			this.opponent = Piece.WHITE;
		}else{
			this.opponent = Piece.BLACK;
		}
		Random rand = new Random();
		int column = -1;
		int colToPlay = easyYiuAI(player);
		if(colToPlay > -1){
			return colToPlay;
		}
		do {
			column = rand.nextInt(Connect4Model.WIDTH);
		} while (!model.isColumnAvailable(column));
		return column;
	}
	
	public int easyYiuAI(Piece player){
		return minimax(0,4,isMaximizingPlayer(player));
	}
	
	public int gameWinCheck(){
		//horizontal check
		for(int row = model.getGameData().size() - 1 ; row >= 0  ; row--){
			for(int col = 0 ; col <= model.getGameData().get(0).size() - 4 ; col++ ){
				if(model.getGameData().get(row).get(col)== model.getGameData().get(row).get(col+1) &&
						model.getGameData().get(row).get(col+1)==model.getGameData().get(row).get(col+2) &&
						model.getGameData().get(row).get(col+2)== model.getGameData().get(row).get(col+3) ){
					if(model.getGameData().get(row).get(col) == player){
						return 10;
					}else if(model.getGameData().get(row).get(col) == opponent){
						return -10;
					}
				}
			}
		}
		
		//vertical check
		for(int row = model.getGameData().size() -1  ; row >= 3; row--){
			for(int col = 0 ; col < model.getGameData().get(0).size() ; col++ ){
				if(model.getGameData().get(row).get(col)==model.getGameData().get(row-1).get(col) &&
						model.getGameData().get(row-1).get(col)==model.getGameData().get(row-2).get(col) &&
						model.getGameData().get(row-2).get(col)== model.getGameData().get(row-3).get(col)){
					if( model.getGameData().get(row).get(col)== player){
						return 10;
					}else if(model.getGameData().get(row).get(col) == opponent){
						return -10;
					}
				}
			}
		}
		
		//Diagonal
		for(int row = 0 ; row <= model.getGameData().size() - 4  ; row++){
			for(int col = 0 ; col <= model.getGameData().get(0).size() - 4 ; col++ ){
				if(model.getGameData().get(row).get(col)==model.getGameData().get(row+1).get(col+1) &&
						model.getGameData().get(row+1).get(col+1)==model.getGameData().get(row+2).get(col+2) &&
						model.getGameData().get(row+2).get(col+2)==model.getGameData().get(row+3).get(col+3) ){
					if( model.getGameData().get(row).get(col)== player){
						return 10;
					}else if(model.getGameData().get(row).get(col) == opponent){
						return -10;
					}
				}
			}
		}
		
		//Diagonal
		for(int row = 0 ; row <= model.getGameData().size() - 4  ; row++){
			for(int col = 3 ; col < model.getGameData().get(0).size() ; col++ ){
				if(model.getGameData().get(row).get(col)==model.getGameData().get(row+1).get(col-1) &&
						model.getGameData().get(row+1).get(col-1)==model.getGameData().get(row+2).get(col-2) &&
						model.getGameData().get(row+3).get(col-3)==model.getGameData().get(row+2).get(col-2)){
					if( model.getGameData().get(row).get(col)== player){
						return 10;
					}else if(model.getGameData().get(row).get(col) == opponent){
						return -10;
					}
				}
			}
		}
		return 0;
	}
	

	
	private boolean isTerminalNode() {
		return false;
	}
	
	private int getHeuristicValue() {
		gameWinCheck();
		//if max player wins, return 5
		//if min player wins, return -5
		// if max player has a threat (ie 3 out of 4) return 2
		//if min player has a threat (ie 3 out of 4) return -2
		//if draw return 1
		//otherwise return 0
		return -1;
	}
	
	private int max(int a1, int a2) {
		if (a1 > a2) {
			return a1;
		} else {
			return a2;
		}
	}
	
	private int min(int a1, int a2) {
		if (a1 < a2) {
			return a1;
		} else {
			return a2;
		}
	}
	
	public boolean isMaximizingPlayer(Piece piece){
		if(piece != player){
			return false;
		}else{
			return true;
		}
	}
	
	public int minimax(int col, int depth, boolean isMaximizingPlayer) {
		Piece[][] copyGameData = model.getGrid();
				
		if (depth == 0 || isTerminalNode()) {
	        return getHeuristicValue();
	    }
	    if (isMaximizingPlayer) {
	        int bestValue = Integer.MIN_VALUE;
	        for (int c = 0; c < Connect4Model.WIDTH ; c++) {
	        	int row = model.getFirstAvailableRow(c);
	        	copyGameData[row][c] = player;
	        	model.set(c, player);
	            int val = minimax(col, depth - 1, false);
	            model.unset(c);
	            bestValue = max(bestValue, val);
	        }
	        return bestValue;
	    }
	    else {
	    	int bestValue = Integer.MAX_VALUE;
	    	for (int c = 0; c < Connect4Model.WIDTH ; c++) {
	    		int row = model.getFirstAvailableRow(c);
	    		copyGameData[row][c] = opponent ;
	    		model.set(c, opponent);
	    		int val = minimax(col, depth - 1, true);
	    		model.unset(c);
	    		bestValue = min(bestValue, val);
	    	}
	    	return bestValue;
	    }
	}
	
}
